﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Transactions;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity;
using Microsoft.Practices.Unity;
using Vallejos.Datos.Factory;
using Vallejos.Datos.Servicios;
using Vallejos.Entidades.Enums;
using Vallejos.Entidades.Interfaces;
using Vallejos.Entidades.ModeloDeDatos;
using Vallejos.Excepciones;

namespace Vallejos.Datos.Accesos
{
    public class PrestamoDAL : IPrestamo
    {
        private readonly DatabaseService _database;
        private readonly SolicitudDAL _solicitud;
        private readonly ComunDAL _comun;


        public PrestamoDAL()
        {
            var container = new UnityContainer()
                .AddNewExtension<EnterpriseLibraryCoreExtension>();
            _database = container.Resolve<DatabaseService>();
            _solicitud = new SolicitudDAL();
            _comun = new ComunDAL();
        }


        private void GuardarHistorialDeSolicitudPrestamo(SolicitudDePrestamo solicitud)
        {
            try
            {
                using (var command = _database.GetStoredProcCommand("GuardarHistorialDeSolicitudPrestamo"))
                {
                    _database.AddInParameter(command, "Id_SolicitudDelPrestamo", DbType.Int32, solicitud.Id);
                    _database.AddInParameter(command, "Id_Estado", DbType.Int32, (int) solicitud.Estado.idEstado);

                    _database.ExecuteNonQuery(command);
                }
            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }
        }

        public List<HistorialDePrestamo> LeerHistorialDeSolicitudDePrestamo(int idPrestamo)
        {
            var historial = new List<HistorialDePrestamo>();

            var factory = new HistorialDePrestamoFactory();

            try
            {
                using (var command = _database.GetStoredProcCommand("LeerHistorialDeSolicitudDePrestamo"))
                {
                    _database.AddInParameter(command, "Id_SolicitudDelPrestamo", DbType.Int32, idPrestamo);

                    using (var reader = _database.ExecuteReader(command))
                        while (reader.Read())
                            historial.Add(factory.Crear(reader));
                }
            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }

            return historial;
        }

        public void AsignarEjecutivoDeSolicitud(SolicitudDePrestamo solicitud)
        {
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew))
                {
                    using (var command = _database.GetStoredProcCommand("AsignarEjecutivoDeSolicitud"))
                    {
                        _database.AddInParameter(command, "Id_SolicitudDePrestamo", DbType.Int32, solicitud.Id);
                        _database.AddInParameter(command, "Id_Ejecutivo", DbType.Int32, solicitud.EjecutivoEncargado.Id);

                        _database.ExecuteNonQuery(command);

                        scope.Complete();
                    }
                }
            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }
        }

        public List<EstadoDePrestamo> LeerEstadosDePrestamo(int idLenguaje)
        {
            var estados = new List<EstadoDePrestamo>();

            var factory = new EstadoDePrestamoFactory();

            try
            {
                using (var command = _database.GetStoredProcCommand("LeerEstadosDePrestamo"))
                {
                    _database.AddInParameter(command, "Id_Lenguaje", DbType.Int32, idLenguaje);

                    using (var reader = _database.ExecuteReader(command))
                        while (reader.Read())
                            estados.Add(factory.Crear(reader));
                }
            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }

            return estados;
        }

        public SolicitudDePrestamo GenerarSolicitudDePrestamo(SolicitudDePrestamo solicitud)
        {
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew))
                {
                    using (var command = _database.GetStoredProcCommand("GenerarSolicitudDePrestamo"))
                    {


                        solicitud.Empleador = _comun.GuardarInformacionDeEmpresa(solicitud.Empleador);
                        solicitud.Servicio = _comun.GuardarInformacionDeServicio(solicitud.Servicio);

                        _database.AddInParameter(command, "Id", DbType.Int32, solicitud.Id);
                        _database.AddInParameter(command, "Id_Vendedor", DbType.Int32, solicitud.Vendedor.Id);

                        if (solicitud.Conyuge != null)
                        {
                            solicitud.Conyuge = _comun.GuardarInformacionPersonal(solicitud.Conyuge);
                            _database.AddInParameter(command, "Id_Conyuge", DbType.Int32, solicitud.Conyuge.Id);
                        }

                        if (solicitud.Socio != null)
                        {
                            solicitud.Socio = _comun.GuardarInformacionPersonal(solicitud.Socio);
                            _database.AddInParameter(command, "Id_Socio", DbType.Int32, solicitud.Socio.Id);
                        }

                        _database.AddInParameter(command, "Id_Empleador", DbType.Int32, solicitud.Empleador.Id);
                        _database.AddInParameter(command, "Id_Servicio", DbType.Int32, solicitud.Servicio.Id);

                        _database.ExecuteNonQuery(command);



                        solicitud.Estado = new EstadoDePrestamo {idEstado = IdEstadoPrestamo.Nuevo};

                        GuardarHistorialDeSolicitudPrestamo(solicitud);

                        scope.Complete();
                    }
                }

            }
            catch (Exception ex)
            {
                throw new ExcepcionDatos("Error desconocido", ex);
            }
            return solicitud;
        }
    }
}